package com.partsoft.dits.utils;

import java.io.Serializable;
import java.util.TimeZone;

import org.springframework.core.NamedInheritableThreadLocal;
import org.springframework.core.NamedThreadLocal;
import org.springframework.util.ObjectUtils;


public abstract class TimeZoneUtils {
	
	private static final ThreadLocal<TimeZoneContext> timeZoneContextHolder = new NamedThreadLocal<TimeZoneContext>("TimeZone context");

	private static final ThreadLocal<TimeZoneContext> inheritableTimeZoneContextHolder =
			new NamedInheritableThreadLocal<TimeZoneContext>("TimeZone context");

	public static TimeZoneContext getTimeZoneContext() {
		TimeZoneContext timeZoneContext = timeZoneContextHolder.get();
		if (timeZoneContext == null) {
			timeZoneContext = inheritableTimeZoneContextHolder.get();
		}
		return timeZoneContext;
	}
	
	/**
	 * 获得当前时区 
	 */
	public static TimeZone getCurrent() {
		TimeZoneContext timeZoneContext = getTimeZoneContext();
		TimeZone currentTimeZone = (timeZoneContext != null ? timeZoneContext.getTimeZone() : TimeZone.getDefault());
		return currentTimeZone;
	}
	
	public static void setTimeZoneContext(TimeZoneContext timeZoneContext) {
		setTimeZoneContext(timeZoneContext, false);
	}
	
	public static void setTimeZoneContext(TimeZoneContext timeZoneContext, boolean inheritable) {
		if (inheritable) {
			inheritableTimeZoneContextHolder.set(timeZoneContext);
			timeZoneContextHolder.set(null);
		}
		else {
			timeZoneContextHolder.set(timeZoneContext);
			inheritableTimeZoneContextHolder.set(null);
		}
	}
	
	public static void setTimeZone(TimeZone newzone) {
		setTimeZone(newzone, false);
	}
	
	public static void setTimeZone(TimeZone newzone, boolean inherite) {
		TimeZoneContext timeZoneContext = (newzone != null ? new SimpleTimeZoneContext(newzone) : null);
		setTimeZoneContext(timeZoneContext, inherite);
	}
	
	public static boolean testCurrent(String zoneid) {
		return getCurrent().equals( getTimeZone(zoneid) );
	}
	
	public static boolean testCurrent( int ofsmins ) {
		return getCurrent().equals(getTimeZone(ofsmins));
	}
	
	public static TimeZone getTimeZone(String zoneid) {
		return TimeZone.getTimeZone(zoneid);
	}
	
	public static TimeZone getTimeZone( int ofsmins ) {
		final StringBuffer sb = new StringBuffer(8).append("GMT");
		if (ofsmins >= 0) {
			sb.append('+');
		} else {
			sb.append('-');
			ofsmins = -ofsmins;
		}
		final int hr = ofsmins / 60, min = ofsmins % 60;
		if (min == 0) {
			sb.append(hr);
		} else {
			if (hr < 10) sb.append('0');
			sb.append(hr).append(':');
			if (min < 10) sb.append('0');
			sb.append(min);
		}
		return TimeZone.getTimeZone(sb.toString());
	}
	
	public static TimeZone getGMTZone() {
		return TimeZone.getTimeZone("GMT");
	}
	
	public static interface TimeZoneContext {

		TimeZone getTimeZone();
		
	}
	

	public static class SimpleTimeZoneContext implements TimeZoneContext, Serializable {
		
		private static final long serialVersionUID = 1022909928030077501L;
		
		private TimeZone timeZone;

		public TimeZone getTimeZone() {
			return timeZone;
		}

		public void setTimeZone(TimeZone timeZone) {
			if (!ObjectUtils.nullSafeEquals(this.timeZone, timeZone)) {
				this.timeZone = timeZone;
				if (this.timeZone == null) {
					this.timeZone = TimeZone.getDefault();
				}
				afterPackaged();
			}
		}
		
		public void afterPackaged() {
			TimeZone.setDefault(this.timeZone);
		}

		public SimpleTimeZoneContext(TimeZone timeZone) {
			this.setTimeZone(timeZone);
		}

	}
}
